package com.ymttest.business.service;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.ymt.core.tool.Logger;
import com.ymttest.utils.JsonBeanHelper;

public class AssertService {

	public static void assertTime(Date expectedDate, Date actualDate, int timeDiffSecond) {
		assertTime(expectedDate,actualDate,timeDiffSecond,"");
	}
	
	//默认10秒
	public static void assertTime(Date expectedDate, Date actualDate, String desc) {
		assertTime(expectedDate,actualDate,10,desc);
	}
	
	
	public static void assertTime(Date expectedDate, Date actualDate, int timeDiffSecond,String desc) {
		Logger.verifyNotNull(expectedDate, "期待时间不该为空");
		Logger.verifyNotNull(actualDate, "实际时间不该为空");

		long time1 = expectedDate.getTime();
		long time2 = actualDate.getTime();
		Logger.verifyEquals(true, Math.abs(time1 - time2) <= timeDiffSecond * 1000,
				desc+", 时间比较,期望时间[" + expectedDate + "],实际时间[" + actualDate + "] 误差应不超过 " + timeDiffSecond + "秒");

	}
	
	

	public static void assertResultContain(JSONObject jsonObject, List<String> nodepathList) {
		for (String nodepath : nodepathList) {
			Logger.verifyEquals(true, JsonBeanHelper.isJsonBeanNodeExist(jsonObject, nodepath),
					"实际值应包含期望值-node paht:" + nodepath);
		}
	}

	/***
	 * 结果比较
	 * 
	 * @param tgtRetMap
	 *            期待结果 tgtRetMap.put("a","1")
	 * 
	 * @param actRetMap
	 *            实际结果 actRetMap.put("a","1")
	 * 
	 *            HashMap<String, Object> tgtRetMap = new HashMap<>();
	 *            tgtRetMap.put("sProductId", 123); tgtRetMap.put("sProduct",
	 *            "name");
	 * 
	 *            YmtProductsIWapper ymtProductsIWapper = new
	 *            YmtProductsIWapper(); List<Map> rm =
	 *            ymtProductsIWapper.selectProductByProductIdforMap("6cd2c583-314e-4f7e-964f-0f41eaae37e5");
	 *            //取出第n条，转换为HashMap HashMap<String, Object> actRetMap =
	 *            (HashMap<String, Object>) rm.get(0);
	 * 
	 *            AssertService.assertResultEqual(tgtRetMap, actRetMap);
	 * 
	 */
	public static void assertResultEqual(Map<String, Object> tgtRetMap, Map<String, Object> actRetMap) {
		assertResultEqual(tgtRetMap, actRetMap, "");
	}

	public static void assertResultEqual(Map<String, Object> tgtRetMap, Map<String, Object> actRetMap, String desc) {
		Logger.verifyEquals(true, tgtRetMap != null, "tgtRetMap should not be null");
		Logger.verifyEquals(true, actRetMap != null, "actRetMap should not be null");

		
		Map<String,Object> tgtRetMapIgnoreCase = new CaseInsensitiveMap(tgtRetMap);
		Map<String,Object> actRetMapIgnoreCase = new CaseInsensitiveMap(actRetMap);
		
		
		for (String actKey : tgtRetMapIgnoreCase.keySet()) {
			if (actRetMapIgnoreCase.containsKey(actKey)) {
				Object tgtNodeObj = tgtRetMapIgnoreCase.get(actKey);
				Object actNodeObj = actRetMapIgnoreCase.get(actKey);
				try {
					Object[] ret = checkWorkAround(tgtNodeObj, actNodeObj);
					if (ret[0] instanceof Date && ret[1] instanceof Date){
						assertTime((Date)ret[0],(Date)ret[1],desc + " 期望值key:[" + actKey + "] 检查");
					}else{
						Logger.verifyEquals(ret[0], ret[1], desc + " 期望值key:[" + actKey + "] 检查");
					}
					
				} catch (Exception e) {
					Logger.verifyEquals(true, false,"key:[" + actKey + "],target value:[" + tgtNodeObj + "],actual value:[" + actNodeObj+"]");
				}
				
			} else {
				Logger.verifyEquals(true, false, "期望值在实际值中不存在  key:[" + actKey + "]");
			}
		}
	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, Map<String, Object> tgtRetMap,
			Map<String, Object> actRetMap) {
		assertResultEqual(tgtAndActKeyPaths, new JSONObject(tgtRetMap), new JSONObject(actRetMap));
	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, JSONObject tgtObject,
			Map<String, Object> actRetMap) {
		assertResultEqual(tgtAndActKeyPaths, tgtObject, new JSONObject(actRetMap));
	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, JSONObject tgtObject,
			Map<String, Object> actRetMap, String desc) {
		assertResultEqual(tgtAndActKeyPaths, tgtObject, new JSONObject(actRetMap), desc);
	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, Map<String, Object> tgtRetMap,
			JSONObject actObject) {
		assertResultEqual(tgtAndActKeyPaths, new JSONObject(tgtRetMap), actObject);
	}

	public static void assertResultEqual(Set<String> keyPaths, Map<String, Object> tgtRetMap, JSONObject actObject) {
		assertResultEqual(keyPaths, new JSONObject(tgtRetMap), actObject);
	}

	public static void assertResultEqual(Set<String> keyPaths, JSONObject tgtObject, JSONObject actObject) {
		Map<String, String> tgtAndActKeyPaths = new HashMap<String, String>();
		for (String key : keyPaths) {
			tgtAndActKeyPaths.put(key, key);
		}
		assertResultEqual(tgtAndActKeyPaths, tgtObject, actObject);

	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, JSONObject tgtObject,
			JSONObject actObject, String desc) {
		Logger.verifyEquals(true, tgtAndActKeyPaths != null, "tgtAndActKeyPaths should not be null");
		Logger.verifyEquals(true, tgtObject != null, "tgtObject should not be null");
		Logger.verifyEquals(true, actObject != null, "actObject should not be null");

		for (String tgtKeyPath : tgtAndActKeyPaths.keySet()) {
			String actKeyPath = tgtAndActKeyPaths.get(tgtKeyPath) == null ? tgtKeyPath
					: tgtAndActKeyPaths.get(tgtKeyPath);

			if (JsonBeanHelper.isJsonBeanNodeExist(tgtObject, tgtKeyPath)) {
				if (JsonBeanHelper.isJsonBeanNodeExist(actObject, actKeyPath)) {
					Object tgtNodeObj = JsonBeanHelper.getJsonBeanNodeObj(tgtObject, tgtKeyPath);
					Object actNodeObj = JsonBeanHelper.getJsonBeanNodeObj(actObject, actKeyPath);
					try {
						Object[] ret = checkWorkAround(tgtNodeObj, actNodeObj);
						Logger.verifyEquals(ret[0], ret[1],
								desc + "期望值 key:[" + tgtKeyPath + "]和实际值 key:[" + actKeyPath + "] 比较检查");

					} catch (Exception e) {
						Logger.verifyEquals(true, false,"key:[" + tgtKeyPath + "],target value:[" + tgtNodeObj + "],actual value:[" + actNodeObj+"]");
					}

				} else {
					Logger.verifyEquals(true, false, desc + "实际值集合中不存在 key:[" + actKeyPath + "]");
				}
			} else {
				Logger.verifyEquals(true, false, desc + "期望值集合中不存在 key:[" + tgtKeyPath + "]");
			}
		}
	}

	public static void assertResultEqual(Map<String, String> tgtAndActKeyPaths, JSONObject tgtObject,
			JSONObject actObject) {
		assertResultEqual(tgtAndActKeyPaths, tgtObject, actObject, "");
	}

	private static Object[] checkWorkAround(Object tgtNodeObj, Object actNodeObj) {
		// for number
		if (tgtNodeObj != null && actNodeObj != null) {
			// 整数，小数，负数
			Pattern pattern = Pattern.compile("\\d+\\.\\d+$|-\\d+\\.\\d+$|^\\d+$|-\\d+$");
			boolean tgtMathcPtnAndActMatchPth = (pattern.matcher(tgtNodeObj.toString()).find()
					&& pattern.matcher(actNodeObj.toString()).find());

			boolean tgtIsNotNumAndActIsNum = !(StringUtils.isNumeric(tgtNodeObj.toString()))
					&& (StringUtils.isNumeric(actNodeObj.toString()));

			boolean tgtIsNumAndActIsNotNum = (StringUtils.isNumeric(tgtNodeObj.toString()))
					&& !(StringUtils.isNumeric(actNodeObj.toString()));

			
			boolean containZimu = (Pattern.compile(".*[a-zA-Z]+.*").matcher(tgtNodeObj.toString()).matches() ||
									Pattern.compile(".*[a-zA-Z]+.*").matcher(actNodeObj.toString()).matches());
			
			boolean containHanzi = (Pattern.compile("([\u4e00-\u9fa5]+)").matcher(tgtNodeObj.toString()).find() ||
					Pattern.compile("([\u4e00-\u9fa5]+)").matcher(actNodeObj.toString()).find());
			
			if (!containHanzi && !containZimu && (tgtIsNotNumAndActIsNum || tgtIsNumAndActIsNotNum || tgtMathcPtnAndActMatchPth)) {
				tgtNodeObj = Double.parseDouble(tgtNodeObj.toString());
				actNodeObj = Double.parseDouble(actNodeObj.toString());
			}
		} else {
			// for null and "","null" ->""
			tgtNodeObj = (tgtNodeObj == null) ? "" : tgtNodeObj;
			actNodeObj = (actNodeObj == null) ? "" : actNodeObj;
		}

		return new Object[] { tgtNodeObj, actNodeObj };
	}

	/**
	 * 2个数组之间对比(String 数组)
	 * 
	 * @param array1
	 *            数组1
	 * @param array2
	 *            数组2
	 * @throws Exception
	 */
	public static void checkArray(String[] array1, String[] array2) {
		checkArray(array1, array2, "");
	}

	public static void checkArray(String[] array1, String[] array2, String desc) {
		try {
			Arrays.sort(array1);
			Arrays.sort(array2);
			
			StringBuffer a1 = new StringBuffer();
			for(int i=0;i<array1.length;i++){
				a1.append(array1[i]+", ");
			}
			
			
			StringBuffer a2 = new StringBuffer();
			for(int i=0;i<array2.length;i++){
				a2.append(array2[i]+", ");
			}
			
			
			boolean aa = Arrays.equals(array1, array2);
			if (aa == true) {
				Logger.verifyEquals(true, aa, desc + ",两个数组中的值相同,["+a1+"],["+a2+"]");
			} else {
				Logger.verifyEquals(true, aa, desc + ",两个数组中的值不相同,["+a1+"],["+a2+"]");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 2个list转String数组对比
	 * 
	 * @param strList1
	 *            list1
	 * @param strList2
	 *            list2
	 * @throws Exception
	 */
	public static void checkArray(List strList1, List strList2) {
		Object[] objs1 = strList1.toArray();
		String[] strs1 = (String[]) strList1.toArray(new String[0]);

		Object[] objs2 = strList2.toArray();
		String[] strs2 = (String[]) strList2.toArray(new String[0]);

		checkArray(strs1, strs2);

	}

	/**
	 * 2个JSONArray转数组数组对比
	 * 
	 * @param strList1
	 * @param strList2
	 * @throws Exception
	 * @throws Exception
	 */
	public static void checkArray(JSONArray strList1, JSONArray strList2) throws Exception {
		checkArray(strList1, strList2, "");
	}

	/**
	 * 2个JSONArray转数组数组对比
	 * 
	 * @param strList1
	 * @param strList2
	 * @throws JSONException
	 * @throws Exception
	 */
	public static void checkArray(JSONArray strList1, JSONArray strList2, String desc) throws Exception {
		String[] strstring1 = new String[strList1.length()];
		String[] strstring2 = new String[strList2.length()];

		for (int i = 0; i < strList1.length(); i++) {
			strstring1[i] = strList1.getString(i);
		}

		for (int i = 0; i < strList2.length(); i++) {
			strstring2[i] = strList2.getString(i);
		}

		checkArray(strstring1, strstring2, desc);

	}

	/**
	 * 2个数组之间对比(int 数组)
	 * 
	 * @param array1
	 *            数组1
	 * @param array2
	 *            数组2
	 * @throws Exception
	 */
	public static void checkArray(int[] array1, int[] array2) throws Exception {
		try {

			Arrays.sort(array1);
			Arrays.sort(array2);
			boolean aa = Arrays.equals(array1, array2);
			if (aa == true) {
				Logger.verifyEquals(true, aa, "两个数组中的值相同");
			} else {
				Logger.verifyEquals(true, aa, "两个数组中的值不相同");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * @SuppressWarnings("unchecked") public static void
	 * assertResultEqual(Object object,JSONObject tgtObject,JSONObject
	 * actObject){ Map<String,String> tgtAndActKeyPaths;
	 * 
	 * if (object instanceof Map){tgtAndActKeyPaths = (Map<String,
	 * String>)object;}
	 * 
	 * if (object instanceof String){ String tmp = (String)object; object =
	 * Arrays.asList(tmp.split(",")); }
	 * 
	 * if (object instanceof Collection){ Collection<String> tmp =
	 * (Collection<String>)object; tgtAndActKeyPaths = new
	 * HashMap<String,String>(); for (String key :
	 * tmp){tgtAndActKeyPaths.put(key, key);} }
	 * 
	 * 
	 * 
	 * }
	 */

	public static boolean assertPreCheck(Object expected, Object actual) {
		Object[] retObj = checkWorkAround(expected, actual);

		if (retObj[0] == null || retObj[1] == null) {
			if (retObj[0] == retObj[1]) {
				return true;
			} else {
				return false;
			}
		} else if (retObj[0].equals(retObj[1])) {
			return true;
		} else {
			return false;
		}
	}

	public static void main(String[] args) {
		System.out.println();
	}

}
